//
//  YYYNetworkManager.swift
//  HotNews
//
//  Created by YYY on 2017/9/29.
//  Copyright © 2017年 成品家（北京）网路科技有限公司. All rights reserved.
//

import UIKit
import AFNetworking

//Swift枚举
enum HttpMethod {
    case POST
    case GET
}
// MARK: 封装AFN的GET、POST请求方法
class YYYNetworkManager: AFHTTPSessionManager {

    //网络工具单例
    //静态区、常量、闭包
    //在第一次访问时，执行闭包，并将结果保存在shared常量中
    static let shared: YYYNetworkManager = {
        //实例化对象
        let instance = YYYNetworkManager()
        //设置响应反序列化支持的数据类型
        instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
        //返回对象
        return instance
    }()
    
    //用户账户的懒加载
    lazy var userAccount = YYYUserAccount()

    //用户是否登录
    var userLoginOn: Bool
    {
        return userAccount.access_token != nil
    }

    /// 专门负责拼接token的方法
    ///
    /// - Parameters:
    ///   - method: 网络请求方法
    ///   - urlString: URL地址
    ///   - parameters: 参数字典
    ///   - name: 上传文件所需要的文件名
    ///   - data: 上传文件所需要的二进制数据
    ///   - completion: 完成回调
    func tokenRequest(method: HttpMethod = .GET, urlString: String, parameters: [String: Any]?, name: String? = nil, data: Data? = nil, completion: @escaping(_ json: Any?, _ isSuccess: Bool)->())
    {
        guard let token = userAccount.access_token else {
            //用户需要登录
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: UserShouldLoginNotification), object: nil)
            //失败的回调
            completion(nil, false)
            return
        }
        var parameters = parameters
        if parameters == nil
        {
            parameters = [String: Any]()
        }
        parameters!["access_token"] = token
        
        //判断name和data
        if let name = name, let data = data
        {
            //上传文件
            upload(URLString: urlString, parameters: parameters, data: data, name: name, completion: completion)
        }
        else
        {
            //普通网络请求
            loadRequest(method: method, urlString: urlString, parameters: parameters, completion: completion)
        }
    }
    
    /// 网络请求GET、POST方法
    /// - Parameters:
    ///   - method: .GET/.POST
    ///   - urlString: urlString
    ///   - parameters: 参数字典
    ///   - completion: 完成回调成功／失败
    func loadRequest(method: HttpMethod = .GET, urlString: String, parameters: [String: Any]?, completion: @escaping(_ json: Any?, _ isSuccess: Bool)->())
    {
        //成功的回调
        let success = { (task: URLSessionDataTask, json: Any?)->() in
            completion(json, true)
        }
        //失败的回调
        let failure = { (task: URLSessionDataTask?, error: Error)->() in
            print("网络加载数据错误：\(error)")
            //用户需要重新登录
            if (task?.response as? HTTPURLResponse)?.statusCode == 403
            {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: UserShouldLoginNotification), object: "token过期")
                print("token 过期，需要重新登录")
            }
            completion(nil, false)
        }
        if method == .GET
        {
            
            get(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
        }
        else
        {
            post(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
        }
    }
}

extension YYYNetworkManager
{
    
    /// 封装AFN的上传文件请求
    ///上传文件只能用post方法，get是获取数据
    /// - Parameters:
    ///   - URLString: URL地址
    ///   - parameters: 参数字典
    ///   - data: 二进制数据
    ///   - name: 服务器规定名称
    ///   - completion: 完成回调
    func upload(URLString: String, parameters: [String: Any]?, data: Data, name: String, completion: @escaping(_ result: Any?, _ isSuccess: Bool)->())
    {
        post(URLString, parameters: parameters, constructingBodyWith: { (formData) in
            
            //创建formData
            //fileName 保存在服务区的文件名，大多数服务器可以随便写
            //mimeType 上传文件的类型
            formData.appendPart(withFileData: data, name: name, fileName: "xxx", mimeType: "application/octet-stream")
        }, progress: nil, success: { (_, json) in
            completion(json, true)
        }) { (task, error) in
            
            if (task?.response as? HTTPURLResponse)?.statusCode == 403
            {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: UserShouldLoginNotification), object: "token过期")
            }
            completion(nil, false)
        }
    }
}
